package com.penglecode.nio.socket;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.util.Date;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class ClientHandler implements ConnectionHandler {

	private static final Log logger = LogFactory.getLog(ClientHandler.class);
	
	/**
	 * 默认读取/写入数据的buffer大小
	 */
	public static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
	
	/**
	 * 默认的数据缓冲区大小(单位字节)
	 */
	private int bufferSize;
	
	/**
	 * Selector对象，负责监控所有的连接到服务器的网络事件的发生
	 */
	private Selector selector;
	
	public ClientHandler(Selector selector) {
		super();
		this.bufferSize = DEFAULT_BUFFER_SIZE;
		this.selector = selector;
	}
	
	/**
	 * 处理客户端连接服务器事件
	 * @param selectionKey	-  客户端选择键对象
	 */
	public void handleConnect(SelectionKey selectionKey){
		SocketChannel client = null;
		try {
			client = (SocketChannel) selectionKey.channel();
			if(client == null){
				return;
			}
			if(client.isConnectionPending()){
				client.finishConnect();
				logger.debug("[Client] : connect to the remote server successfully!");
			}
			//selectionKey.interestOps(SelectionKey.OP_WRITE);
			client.register(this.selector, SelectionKey.OP_WRITE);
		} catch (IOException e) {
			logger.error(e, e);
			IOUtils.closeQuietly(client);
		}
	}
	
	/**
	 * 进行读取服务端数据操作
	 * @param selectionKey	- 客户端选择键对象
	 */
	public void handleRead(SelectionKey selectionKey) {
		SocketChannel client = null;
		client = (SocketChannel) selectionKey.channel();
		/*//得到附件，就是上面handleServerSocketEvent方法中register方法调用的第三个输入参数
		ByteBuffer buffer = (ByteBuffer) selectionKey.attachment();*/
		ByteBuffer buffer = ByteBuffer.allocate(bufferSize);
		byte[] datas = BufferUtils.read(client, buffer);
		logger.debug(String.format("[Client] read message from server : %s", new String(datas, Charset.defaultCharset())));
		//从客户端读到了数据,下一步注册向客户端写数据事件
		selectionKey.interestOps(SelectionKey.OP_WRITE);
		selectionKey.attach(datas);
	}
	
	/**
	 * 进行向客户端写数据操作
	 * @param selectionKey	- 客户端选择键对象
	 */
	public void handleWrite(SelectionKey selectionKey) {
		SocketChannel client = null;
		client = (SocketChannel) selectionKey.channel();
		String message = "现在时间：" + DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss") + " , " + System.currentTimeMillis();
		byte[] datas = message.getBytes(Charset.defaultCharset());
		ByteBuffer buffer = ByteBuffer.allocate(bufferSize);
		BufferUtils.write(client, buffer, datas);
		//注册向客户端读数据事件
		selectionKey.interestOps(SelectionKey.OP_READ);
		selectionKey.attach(datas);
	}
	
}
